<template>
    <div class="flex-col justify-between" style="height: 95%;overflow-y: hidden;">
        <n-form ref="formRef" :model="form" :rules="rules" label-placement="top"
                label-width="120" require-mark-placement="right-hanging" style="height: 100%;overflow-y: auto;">
            <n-form-item label="是否仅知识库模式" path="onlyKlb">
                <n-radio-group v-model:value="klbChatForm.onlyKlb" name="radiogroup">
                    <n-space>
                        <n-radio :value="true">
                            是
                        </n-radio>
                        <n-radio :value="false">
                            否
                        </n-radio>
                    </n-space>
                </n-radio-group>
            </n-form-item>
            <n-form-item label="未匹配到知识库资料时回复" path="noMatchReply" v-if="klbChatForm.onlyKlb">
                <n-input v-model:value="klbChatForm.noMatchReply" name="radiogroup">
                </n-input>
            </n-form-item>
            <n-form-item label="是否开启视觉增强" path="klbChatForm.showWithHtml">
                <template #label>
                    <div class="flex items-center">
                        <span>是否开启视觉增强</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            开启视觉增强功能后，AI会将回答内容以更丰富的视觉效果进行展示。
                            <br>
                            注意：开启后会导致token消耗增加。
                        </n-tooltip>
                    </div>
                </template>
                <n-radio-group v-model:value="klbChatForm.showWithHtml" name="radiogroup">
                    <n-space>
                        <n-radio :value="true">
                            是
                        </n-radio>
                        <n-radio :value="false">
                            否
                        </n-radio>
                    </n-space>
                </n-radio-group>
            </n-form-item>
            <n-form-item label="选择AI模型" path="name">
                <jb-select url="aiResource/listAllEnabledType" labelField="name" placeholder="请选择AI模型" valueField="sn"
                           v-model:value="form.model"></jb-select>
            </n-form-item>

            <n-form-item label="是否保持上下文" path="useContext">
                <n-radio-group v-model:value="form.useContext" name="radiogroup">
                    <n-space>
                        <n-radio :value="true">
                            是
                        </n-radio>
                        <n-radio :value="false">
                            否
                        </n-radio>
                    </n-space>
                </n-radio-group>
            </n-form-item>
            <n-form-item label="">
                <template #label>
                    <div class="flex items-center">
                        <span>Max_Tokens</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            该参数可以理解为一次对话的"字数限制"，它决定了AI能回应的最大文字量。如果超过这个限制，AI就会停止输出或无法处理。
                            <br>
                            注意：不同大模型的max_tokens可取范围不同，请参考具体大模型文档。
                        </n-tooltip>
                    </div>
                </template>
                <n-input-number style="width: 100%" v-model:value="form.maxTokens" placeholder="请输入Max_Tokens"
                                max="8192"></n-input-number>
            </n-form-item>
            <n-form-item label="temperature">
                <template #label>
                    <div class="flex items-center">
                        <span>temperature</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            Temperature参数就像是AI的"冒险度"调节器。数值越高，AI回答越随机多样化，可能更有创意但也更不可预测；数值越低，AI回答越稳定可靠，但可能显得更公式化。简单来说，它控制着AI是更喜欢安全常规的回答，还是更愿意冒险尝试新奇的表达。
                            <br>
                            默认值：0.6。不同大模型的temperature可取范围不同，请参考具体大模型文档。
                        </n-tooltip>
                    </div>
                </template>
                <n-input style="width: 100%"  v-model:value="form.temperature"
                         placeholder="请输入temperature"></n-input>
            </n-form-item>
            <n-form-item label="" path="minScore">
                <template #label>
                    <div class="flex items-center">
                        <span>知识库查询文档相关性最小分值</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            建议:minScore参数:文档相关性分值要>=0.6
                        </n-tooltip>
                    </div>
                </template>
                <div style="display: flex;flex-direction: column;width: 100%">
                    <n-slider v-model:value="klbSearchForm.minScore" :step="0.1" :max="1" :min="0"/>
                </div>
            </n-form-item>
            <n-form-item label="">
                <template #label>
                    <div class="flex items-center">
                        <span>知识库查询条数</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            知识库搜索的数据库查询条数
                        </n-tooltip>
                    </div>
                </template>
                <n-input-number style="width: 100%" v-model:value="klbSearchForm.limit" placeholder="请输入知识库搜索的数据库查询条数"
                                max="100"></n-input-number>
            </n-form-item>


            <n-form-item label="System Message">
                <template #label>
                    <div class="flex items-center">
                        <span>System Message</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            System Message参数就像是给AI设定的"角色说明书"。它告诉AI应该扮演什么角色、用什么风格说话以及遵循哪些规则。简单来说，它决定了AI的个性和行为方式，就像是给演员的表演指导。
                            <br>示例：
                            <br>- 设定角色：例如，“你是一个知识渊博的中文助手。”
                            <br>- 定义行为规范：如，“请以简洁明了的方式回答问题。”
                            <br>- 限制内容：例如，“避免讨论敏感话题。”
                        </n-tooltip>
                    </div>
                </template>
                <n-input v-model:value="form.systemRole" type="textarea" style="min-height: 200px"
                         placeholder="请输入System Message"></n-input>
            </n-form-item>
            <n-form-item label="Prompt模版">
                <template #label>
                    <div class="flex items-center">
                        <span>Prompt模版</span>
                        <n-tooltip trigger="hover" :style="{ maxWidth: '400px' }">
                            <template #trigger>
                                <div>
                                    <jb-icon :local="true" icon="mingcute:information-line" class="ms-1" width="18" color="#aaaaaa"></jb-icon>
                                </div>
                            </template>
                            Prompt模版用于重新构建提问内容，你可以在模板中通过${prompt}引入用户的原始提问。
                            <br>
                            示例：
                            <br> 模板设置为：请将`${prompt}`翻译为英文。
                            <br>当用户提问：你是谁? 的时候，AI实际收到的提问是：请将`你是谁?`翻译为英文。
                        </n-tooltip>
                    </div>
                </template>
                <n-input v-model:value="form.promptTpl" type="textarea" style="min-height: 200px"
                         placeholder="请输入Prompt模版"></n-input>
            </n-form-item>
        </n-form>
        <div class="flex justify-center">
            <jb-btn type="primary" @click="handleSubmit">提交-更新LLM参数配置</jb-btn>
        </div>
    </div>
</template>

<script setup>
import {
    onMounted,
    ref,watch
} from 'vue'
import {
    JBoltApi
} from '@/service/request'
import {showSuccessMsg} from '@/utils/service/msg.js'

const props = defineProps({
    appId: {
        type: String
    },
})

const formRef = ref(null)

const form = ref({
    useContext: true,
    maxTokens: 2000,
    temperature: '0.6',
    topP: 0,
    topK: 0,
    systemRole: '',
    inputField:'prompt',
    promptTpl: "",
    model: '',
})
const klbChatForm = ref({
    noMatchReply: '抱歉您的问题无法回答',
    onlyKlb: true,
    showWithHtml: false,
})
const klbSearchForm = ref({
    limit: 6,
    minScore: 0.6
})

const rules = {
    maxTokens: {
        required: true,
        message: '请输入maxTokens',
        trigger: 'change'
    },
    temperature: {
        required: true,
        message: '请输入temperature',
        trigger: 'change'
    },
    topP: {
        required: true,
        message: '请输入top_p',
        trigger: 'change'
    },
    topK: {
        required: true,
        message: '请输入top_k',
        trigger: 'change'
    },
}

//------监听用户当前是否有更改的数据
const emit = defineEmits(['unSaveData', 'saveData']);
const oldForm = ref({})
const oldKlbChatForm = ref({})
const oldKlbSearchForm = ref({})
// 深度比较两个对象
const hasChangeLlmForm = () => {
    return JSON.stringify(oldForm.value) !== JSON.stringify(form.value);
};
//监听表单的值变化
watch(() => form.value, (newValue, oldValue) => {
    if (hasChangeLlmForm() == false) {
        emit('saveData')
    } else {
        emit('unSaveData')
    }

}, {deep: true})
// 深度比较两个对象
const hasChangeKlbChatForm = () => {
    return JSON.stringify(oldKlbChatForm.value) !== JSON.stringify(klbChatForm.value);
};
watch(() => klbChatForm.value, (newValue, oldValue) => {
    if (hasChangeKlbChatForm() == false) {
        emit('saveData')
    } else {
        emit('unSaveData')
    }

}, {deep: true})
// 深度比较两个对象
const hasChangeKlbSearchForm = () => {
    return JSON.stringify(oldKlbSearchForm.value) !== JSON.stringify(klbSearchForm.value);
};
watch(() => klbSearchForm.value, (newValue, oldValue) => {
    if (hasChangeKlbSearchForm() == false) {
        emit('saveData')
    } else {
        emit('unSaveData')
    }

}, {deep: true})

//------监听用户当前是否有更改的数据


async function handleSubmit() {
    await formRef.value?.validate()
    if (!form.value.promptTpl.trim()) {
        form.value.inputField = 'prompt';
    } else {
        form.value.inputField = 'jb_custom';
    }
    // console.log('提交表单', JSON.stringify(form.value))
    let url = '/aiAppConfig/updateConfigListByKeyList';
    await JBoltApi.post(url, {
        linkType: 'app',
        linkId: props.appId,
        configList: [
            {
                configKey: 'llmConfig',
                configValue: JSON.stringify(form.value)
            },
            {
                configKey: 'klbChatConfig',
                configValue: JSON.stringify(klbChatForm.value)
            },
            {
                configKey: 'klbSearchConfig',
                configValue: JSON.stringify(klbSearchForm.value)
            }
        ]
    }).then(res => {
        showSuccessMsg('保存成功');
        oldForm.value = { ...form.value};
        oldKlbChatForm.value = { ...klbChatForm.value};
        oldKlbSearchForm.value={ ...klbSearchForm.value}
        emit('saveData');
    });
}


function loadConfigData() {
    JBoltApi.tryPost(`/aiAppConfig/getConfigListByCondition`, {
        linkType: "app",
        linkId: props.appId,
        configKeyList: ['llmConfig', 'klbChatConfig', 'klbSearchConfig'] // 使用数组来包含多个configKey
    }).then(res => {
        if (res.data) {
            if (res.data.llmConfig) {
                form.value = { ...form.value, ...res.data.llmConfig }; // 合并现有属性与新获取的属性
                form.value.temperature = res.data.llmConfig.temperature.toString();
                oldForm.value = { ...form.value};
            }
            if (res.data.klbChatConfig) {
                klbChatForm.value = {...res.data.klbChatConfig };
                oldKlbChatForm.value = { ...klbChatForm.value};
            }
            if(res.data.klbSearchConfig){
                klbSearchForm.value = {...res.data.klbSearchConfig };
                oldKlbSearchForm.value = { ...klbSearchForm.value};
            }
        }
    }).catch((error) => {
        console.error(error);
    })
}


onMounted(() => {
    if (props.appId) {
        loadConfigData()
    }
})
</script>

<style scoped lang="scss">
</style>